package com.taiji.dianthus.service.sys.impl;


import com.taiji.dianthus.common.BusinessMessage;
import com.taiji.dianthus.dao.sys.MenuRoleRepository;
import com.taiji.dianthus.dao.sys.RoleRepository;
import com.taiji.dianthus.domain.sys.DSysRole;
import com.taiji.dianthus.domain.sys.DSysRoleMenu;
import com.taiji.dianthus.service.sys.MenuRoleService;
import com.taiji.dianthus.service.sys.RoleService;
import com.taiji.dianthus.service.sys.RoleUserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import static com.taiji.dianthus.common.Constant.LOG_OPERATION_SAVE;

/**
 * @ClassName RoleServiceImpl
 * @Description
 * @Author H.M
 * @Date 2019/12/24
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class RoleServiceImpl implements RoleService {

    @Autowired
    private RoleRepository roleRepository;

    @Autowired
    private MenuRoleRepository menuRoleRepository;

    @Autowired
    private MenuRoleService menuRoleService;

    @Autowired
    private RoleUserService roleUserService;

    /**
     * 获取所有角色
     *
     * @return
     */
    @Override
    public BusinessMessage listRoles(Integer pageSize, Integer currentPage) {
        BusinessMessage message = new BusinessMessage();
        try {
            //排序
            Sort sort = new Sort(Sort.Direction.DESC, "createTime");
            //分页参数
            Pageable pageable = PageRequest.of(currentPage, pageSize, sort);
            Page<DSysRole> rolesPage;
            Specification<DSysRole> spec = (Root<DSysRole> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> {
                List<Predicate> pl = new ArrayList<Predicate>();
                // 查询出未删除的
                pl.add(cb.equal(root.<Integer>get("enableFlag"), 1));
                return cb.and(pl.toArray(new Predicate[0]));
            };
            rolesPage = roleRepository.findAll(spec, pageable);
            message.setData(rolesPage);
            message.setSuccess(true);
            message.setMsg("查询角色列表成功");
        } catch (Exception e) {
            e.printStackTrace();
            message.setMsg("查询角色列表失败");
        }

        return message;
    }

    /**
     * 根据ID详情
     *
     * @param id
     * @return
     */
    @Override
    public DSysRole getRoleById(String id) {
        return roleRepository.getOne(id);
    }

    /**
     * 保存角色
     *
     * @param role
     * @return
     */
    @Override
    public BusinessMessage saveRole(DSysRole role) {
        BusinessMessage message = new BusinessMessage();
        try {
            //如果是编辑
            if (!StringUtils.isEmpty(role.getId())) {
                DSysRole oldRole = roleRepository.getOne(role.getId());
                //角色名称去重判断
                if (!oldRole.getRoleDesc().equals(role.getRoleDesc())) {
                    Integer existsDesc = roleRepository.existsDSysRoleByRoleDesc(role.getRoleDesc());
                    if (null != existsDesc) {
                        message.setMsg("保存失败，角色名称已经存在");
                        return message;
                    }
                }
                //角色代码去重判断
                boolean flag = !StringUtils.isEmpty(role.getRoleName()) && !oldRole.getRoleName().equals(role.getRoleName());
                if (flag) {
                    Integer existsName = roleRepository.existsDSysRoleByRoleName(role.getRoleName());
                    if (null != existsName) {
                        message.setMsg("保存失败，角色代码已经存在");
                        return message;
                    }
                }
            } else {
                Integer existsDesc = roleRepository.existsDSysRoleByRoleDesc(role.getRoleDesc());
                if (null != existsDesc) {
                    message.setMsg("保存失败，角色名称已经存在");
                    return message;
                }
                if (!StringUtils.isEmpty(role.getRoleName())) {
                    Integer existsName = roleRepository.existsDSysRoleByRoleName(role.getRoleName());
                    if (null != existsName) {
                        message.setMsg("保存失败，角色代码已经存在");
                        return message;
                    }
                }
            }
            //角色代码去重判断
            roleRepository.save(role);
            message.setSuccess(true);
            message.setMsg("保存角色成功！");
        } catch (Exception e) {
            e.printStackTrace();
            message.setMsg("保存角色失败！");
        } finally {
            return message;
        }

    }

    /**
     * @param menuIds 选择的菜单Id的字符串，以逗号分隔的
     * @param roleId  void  选择的角色Id
     * @Description: 保存角色菜单的分配
     */
    @Override
    public BusinessMessage saveOrUpdateRoleMenu(String menuIds, String roleId) {
        BusinessMessage message = new BusinessMessage();
        try {
            String[] menuIdsArr = menuIds.split(",");
            if (menuIdsArr.length == 0) {
                message.setMsg("选择的权限为空");
                return message;
            }
            List<String> menuIdList = Arrays.asList(menuIdsArr);
            //原有角色的菜单权限
            List<String> preMenuIds = menuRoleService.getMenuIdsByRoleId(roleId);
            //求差集
            List<String> differenceSet = menuIdList.stream().filter(t -> !preMenuIds.contains(t)).collect(Collectors.toList());
            List<String> differenceSet2 = preMenuIds.stream().filter(t -> !menuIdList.contains(t)).collect(Collectors.toList());
            //此处指的是将与l2重复的删除
            differenceSet.removeAll(differenceSet2);
            //此处指加上l2
            differenceSet.addAll(differenceSet2);
            for (int i = 0; i < differenceSet.size(); i++) {
                String did = differenceSet.get(i);
                //取差集中在旧ID中进行删除
                if (null != preMenuIds && preMenuIds.size() > 0 && !org.springframework.util.StringUtils.isEmpty(did) && preMenuIds.contains(did)) {
                    DSysRoleMenu menuRole = new DSysRoleMenu();
                    menuRole.setRoleId(roleId);
                    menuRole.setMenuId(did);
                    menuRoleService.delete(menuRole);
                    //取差集中在新ID中进行存储
                } else if (!org.springframework.util.StringUtils.isEmpty(did) && menuIdList.contains(did)) {
                    DSysRoleMenu menuRole = new DSysRoleMenu();
                    menuRole.setRoleId(roleId);
                    menuRole.setMenuId(did);
                    menuRoleService.save(menuRole);
                }
            }
            message.setSuccess(true);
            message.setMsg("保存成功");

        } catch (Exception e) {
            e.printStackTrace();
            message.setMsg("系统异常");

        } finally {
            return message;
        }

    }

    /**
     * 删除方法
     *
     * @param id
     */
    @Override
    public BusinessMessage deleteRole(String id) {
        BusinessMessage message = new BusinessMessage();
        Integer result = roleUserService.countByRole(id);
        try {
            if ( result > 0 ) {
                message.setMsg("角色下存在用户，不能删除");
            } else {
                roleRepository.updateFlag(id);
                menuRoleService.deleteByRole(id);
                message.setSuccess(true);
                message.setMsg("删除成功");
            }
        } catch (Exception e) {
            e.printStackTrace();
            message.setMsg("删除失败");
        }
        return message;
    }

    /**
     * 查询所有角色
     *
     * @return
     */
    @Override
    public List<DSysRole> listAll() {
        return roleRepository.listAll();
    }


}
